layui.define(['laytpl', 'jquery', 'table'], function (exports) {
    let $ = layui.jquery;
    let laytpl = layui.laytpl;
    let defaultConfig = {
        idKey: 'id',
        parentIdKey: 'parentId',
        childrenKey: 'children',
        titleKey: 'name',
        titleLabel: '名称',
        titleLabelWidth: 300,
        ele: '#tableView',
        url: '',
        itemIcon: 'layui-icon-file',
        cols: []
    };

    let treeGrid = {
        config: {},
        data: [],
        render: function (config) {
            let $this = this;
            $('body').append(' <style>.tree-row-hidden{display: none;}</style>');
            config = $.extend({}, defaultConfig, config);
            this.config = $.extend({}, this.config, config);
            let template = '<table class="layui-table">';
            template += '<thead>';
            template += '<tr>';
            template += '<th style="width:' + this.config.titleLabelWidth + 'px">';
            template += this.config.titleLabel;
            template += '</th>';
            template += this.renderHead();
            template += '</tr>';
            template += '</thead>';
            template += '<tbody>';
            template += '{{d}}';
            template += '</tbody>';
            template += '</table>';

            if (config.url) {
                $.ajax({
                    url: config.url,
                    success: function (data) {

                        let d = $this.preorder($this.getTree(data.data), 1);
                        this.data = d;
                        laytpl(template).render($this.renderRow($this.getTree(data.data), 1), function (html) {
                            $($this.config.ele).html(html);
                        });
                        $.each($(config.ele).next('div').find('tbody').children('tr'), function (index, item) {
                            $(item).attr('data-tt-id', d[index][config.idKey]);
                            $(item).attr('data-tt-parent-id', d[index][config.parentIdKey]);
                            $(item).attr('data-tt-level', d[index].level);
                            $(item).attr('data-tt-leaf', d[index].leaf);
                        })
                        $('tr[data-tt-level]').addClass('tree-row-hidden');
                        $('tr[data-tt-level=1]').removeClass('tree-row-hidden');
                        $('tr[data-tt-leaf=true]').find('.tree-icon').removeClass('layui-icon-triangle-r').addClass(config.itemIcon);
                        $('.tree-icon').on('click', function (e) {
                            if ($(this).hasClass('layui-icon-triangle-r')) {
                                $(this).removeClass('layui-icon-triangle-r').addClass('layui-icon-triangle-d');
                                let id = $(this).parents('tr').eq(0).data('tt-id');
                                $('tr[data-tt-parent-id=' + id + ']').removeClass('tree-row-hidden');
                            } else {
                                $(this).removeClass('layui-icon-triangle-d').addClass('layui-icon-triangle-r');
                                let id = $(this).parents('tr').eq(0).data('tt-id');
                                $this.hiddenChildren(id);
                            }
                        })
                    }
                })

            }
        },
        renderRow: function (datas, level) {
            if (datas && datas.length) {
                let str = '';
                for (let i = 0, len = datas.length; i < len; i++) {
                    let item = datas[i];
                    let leaf = !(item.children && item.children.length);
                    str += '<tr data-tt-id="' + item.id + '" data-tt-parent-id="' + item[this.config.parentIdKey] + '" data-tt-level="' + level + '" data-tt-leaf="' + leaf + '">';
                    str += '<td><span class="indenter" style="padding-left:' + level * 10 + 'px"></span><i class="layui-icon layui-icon-triangle-r tree-icon"></i>' + item.name + '</td>';
                    str += this.renderCol(item);
                    str += this.renderRow(item.children, level + 1);
                }
                return str;
            } else {
                return '';
            }
        },
        renderHead() {
            let str = '';
            for (let i = 0, len = this.config.cols.length; i < len; i++) {
                let item = this.config.cols[i];
                str += '<th' + (item.width ? ' style="width:' + item.width + 'px"' : '') + '>' + item.title + '</th>';
            }
            return str;
        },
        renderCol(data) {
            let str = '';
            for (let i = 0, len = this.config.cols.length; i < len; i++) {
                let item = this.config.cols[i];
                if (typeof item.templet === 'function') {
                    str += '<td>' + item.templet(data, item) + '</td>';
                } else {
                    str += '<td>' + data[item.field] + '</td>';
                }
            }
            return str;
        },
        hiddenChildren: function (id) {
            let $this = this;
            $('tr[data-tt-parent-id=' + id + ']').addClass('tree-row-hidden');
            $.each($('tr[data-tt-parent-id=' + id + ']'), function (index, item) {
                let iid = $(item).data('tt-id');
                $('tr[data-tt-id=' + iid + '][data-tt-leaf=false]').find('.tree-icon').removeClass('layui-icon-triangle-d').addClass('layui-icon-triangle-r');
                $this.hiddenChildren($(item).data('tt-id'));
            })
        },
        getTree: function (node) {
            let root = [];
            for (let i = 0; i < node.length; i++) {
                if (Number(node[i][this.config.parentIdKey]) <= 0) {
                    root.push(node[i]);
                }
            }
            return this.buildTree(node, root);
        },
        buildTree: function (node, root) {
            for (let i = 0; i < root.length; i++) {
                let children = [];
                for (let k = 0; k < node.length; k++) {
                    if (node[k][this.config.parentIdKey] == root[i][this.config.idKey]) {
                        children.push(node[k]);
                    }
                }
                if (children.length != 0) {
                    root[i][this.config.childrenKey] = children;
                    this.buildTree(node, children);
                }
            }
            return root;
        },
        preorder: function (tree, level) {
            let array = [];
            for (let i = 0; i < tree.length; i++) {
                tree[i].level = level;
                if (tree[i][this.config.childrenKey] != null) {
                    tree[i].leaf = false;
                    array.push(tree[i]);
                    array = array.concat(this.preorder(tree[i][this.config.childrenKey], level + 1));
                } else {
                    tree[i].leaf = true;
                    array.push(tree[i]);
                }
                tree[i][this.config.childrenKey] = [];
            }
            return array;
        }
    }
    exports('treeGrid', treeGrid);
});